#!/usr/bin/python
# -*- encoding: UTF-8 -*-

from __future__ import print_function

import gtk
#gtk.gdk.threads_init()

import os
import sys
import time

import ascensores
import plc
import scada_gtk

class dialogo(gtk.Dialog):

    def _cerrar(self, button):
        self.d.destroy()                

    def _armar_mensaje(self, pasos):
        aux = "<b>Pasos:</b>\n"
        for n,l in enumerate(pasos):
            if n < 9:
                aux+="<tt> {0}</tt>. {1}\n".format(n+1,l)
            else:
                aux+="<tt>{0}</tt>. {1}\n".format(n+1,l)
        return aux

    def __init__(self, titulo, mensaje):
        self.d = gtk.Dialog(  title=titulo, parent=None,
                              flags=gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
                              buttons=(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE, gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)) #gtk.BUTTONS_NONE, gtk.BUTTONS_OK, 
        label = gtk.Label(self._armar_mensaje(mensaje))
        label.set_use_markup(True)

        self.d.vbox.pack_start(label)
        label.show()

        cerrar = self.d.get_widget_for_response(gtk.RESPONSE_CLOSE)
        cerrar.connect("pressed", self._cerrar)

    def run(self):
        resultado = self.d.run()
        if resultado == gtk.RESPONSE_CLOSE:
            self.d.destroy()

class Escenario:
    '''
        Clase encargada de lanzar las personas que activan las interacciones del escenario.
    '''
    def __init__(self, nombre = "", pasos = [], personas = []):
        self.nombre = nombre # Nombre indicativo del escenario.
        self.pasos = pasos # Pasos que cumple el escenario.
        self.personas = personas # Personas del escenario.

    def aplicar(self, modelo):
        '''
            Aplicar el escenario a un determinado modelo.
        '''
        for p in self.personas:
            if not modelo is None:
                modelo.registrar_persona(p)
                p.edificio = modelo
                p.start()


class una_persona_atencion_criticos (Escenario):
    def __init__(self, modelo = None):
        Escenario.__init__(self,nombre = "Prueba 1")

        self.pasos = [
            "Ambos ascensores en planta baja.",
            "Los pisos criticos son la planta baja y el 10, para cualquier horario.",
            "Un usuario llama a desde el piso 5. Un ascensor libre es asignado.",
            "Mientras que un ascensor esta en transito, se analiza los pisos criticos.",
            "Al entrar una persona al ascensor, se encienden la luz y la ventilacion.",
            "Un ascensor esta en transito y el otro esta en un piso critico. No hay cambios.",
            "El ascensor en transito sube a su pasajero en el piso 5, y viaja a planta baja.",
            "Al llegar el pasajero se baja, el ascensor apaga las luces y la ventilacion.",
            "Un nuevo proceso de analisis de pisos criticos, pero esta vez con dos ascensores libres en la planta baja.",
            "Uno de los ascensores se envia al piso 10.",
            "El sistema queda a la espera de nuevas personas."
        ]

        p1 = ascensores.Persona("P1", modelo, inicio=5, destino=1, peso=85, delay=1)
        self.personas.append(p1)

class cuatro_personas_piden_desde_el_mismo_piso (Escenario):
    def __init__(self, modelo = None):
        Escenario.__init__(self,nombre = "Prueba 2")

        self.pasos = [
            "Ambos ascensores en planta baja.",
            "Los pisos criticos son la planta baja y el 10, para cualquier horario.",
            "Cuatro personas llaman a desde el piso 7, en distintos instantes.",
            "Un ascensor libre es asignado.",
            "Mientras que un ascensor esta en transito, se analiza los pisos criticos.",
            "Al entrar una persona al ascensor, se encienden la luz y la ventilacion.",
            "Un ascensor esta en transito y el otro esta en un piso critico. No hay cambios.",
            "Una de las personas llena el ascensor y se activa la alarma de peso.",
            "Esa persona deciende.",
            "El ascensor se pone en marcha una vez cerradas las puertas.",
            "Cada pasajero tiene un destino distinto.",
            "Al bajarse el utlimo pasajero, el ascensor apaga las luces y la ventilacion.",
            "Un nuevo proceso de analisis de pisos criticos, pero esta vez con dos ascensores libres en la planta baja.",
            "Uno de los ascensores se envia al piso 10.",
            "El sistema queda a la espera de nuevas personas."
        ]

        p1 = ascensores.Persona("P1", modelo, inicio=7, destino=6, peso=85, delay=0.25)
        self.personas.append(p1)
        p2 = ascensores.Persona("P2", modelo, inicio=7, destino=0, peso=85, delay=0.5)
        self.personas.append(p2)
        p3 = ascensores.Persona("P3", modelo, inicio=7, destino=5, peso=85, delay=0.75)
        self.personas.append(p3)
        p4 = ascensores.Persona("P4", modelo, inicio=7, destino=4, peso=85, delay=1)
        self.personas.append(p4)

class priorizar_mas_cercano (Escenario):
    def __init__(self, modelo = None):
        Escenario.__init__(self,nombre = "Prueba 3")

        self.pasos = [
            "Ambos ascensores en planta baja.",
            "Los pisos criticos son la planta baja y el 10, para cualquier horario.",
            "Se analiza los pisos criticos.",
            "Un ascensor se envia al piso 10.",
            "Una persona aparece luego de que hay un ascensor en el piso 10 y otro en el 0.",
            "La persona aparece en el piso 4 y quiere ir a planta baja.",
            "Debe ser atentido por el ascensor que esta ubicado en planta baja.",
            "Al entrar una persona al ascensor, se encienden la luz y la ventilacion.",
            "Esa persona deciende.",
            "Al bajarse el utlimo pasajero, el ascensor apaga las luces y la ventilacion.",
            "Un nuevo proceso de analisis de pisos criticos, pero esta vez con dos ascensores libres en la planta baja.",
            "Uno de los ascensores se envia al piso 10.",
            "El sistema queda a la espera de nuevas personas."
        ]
        p1 = ascensores.Persona("P1", modelo, inicio=4, destino=0, peso=85, delay=30)
        self.personas.append(p1)

class muchas_personas (Escenario):
    def __init__(self, modelo = None):
        Escenario.__init__(self,nombre = "Prueba 4")

        self.pasos = [
            "Ambos ascensores en planta baja.",
            "Los pisos criticos son la planta baja y el 10, para cualquier horario.",
            "Varias personas solicitan transporte desde distintos pisos.",
            "Las ultimas dos personas solicitan desde el mismo origen.",
            "Una quiere ir desde el 5to al 9vo y otra quiere ir al 3ro.",
            "Como el 3ro esta mas cerca el ascensor debe ir a ese piso y luego ir al 9vo.",
            "El sistema queda a la espera de nuevas personas."
        ]
        p1 = ascensores.Persona("P1", modelo, inicio=4, destino=0, peso=85, delay=1)
        self.personas.append(p1)
        p2 = ascensores.Persona("P2", modelo, inicio=7, destino=0, peso=85, delay=1)
        self.personas.append(p2)
        p4 = ascensores.Persona("P4", modelo, inicio=8, destino=10, peso=85, delay=3)
        self.personas.append(p4)
        p5 = ascensores.Persona("P5", modelo, inicio=10, destino=0, peso=85, delay=5)
        self.personas.append(p5)
        p6 = ascensores.Persona("P6", modelo, inicio=5, destino=3, peso=85, delay=9)
        self.personas.append(p6)
        p7 = ascensores.Persona("P7", modelo, inicio=5, destino=9, peso=85, delay=10)
        self.personas.append(p7)

if __name__ == "__main__":
#    escenarios = {}
#    escenarios["Prueba1"] = una_persona_atencion_criticos()
#    escenarios["Prueba2"] = cuatro_personas_piden_desde_el_mismo_piso()

    escenario = None
    if len(sys.argv) > 1:
        nombre = sys.argv[1].strip()

        if nombre == "Prueba1":
            escenario = una_persona_atencion_criticos()
        elif nombre == "Prueba2":
            escenario = cuatro_personas_piden_desde_el_mismo_piso()
        elif nombre == "Prueba3":
            escenario = priorizar_mas_cercano()
        elif nombre == "Prueba4":
            escenario = muchas_personas()
        else:
            print ("El escenario '{0}' no esta definido.".format(sys.argv[1].strip()), file=sys.stderr)
            exit(1)

        # Lanzo el dialogo de ayuda del escenario.
        m = dialogo(escenario.nombre, escenario.pasos)
        m.run()

    # Creo el modelo del edificio.
    model = ascensores.Edificio('E1',11)

    # Construyo los ascensores.
    asc = list()
    for i in xrange(2):
        # Por cada ascensor: lo creo, inicializo, asocio una vista, y un controlador. Finalmente lo guardo en una lista para registrarlo en el edifico.
        a_model = ascensores.Ascensor()
        a_model.inicializar( nombre = "A"+str(i+1), velocidad = 2.0 , capacidad = 3*85, posicion = 0, tope=11)
        a_view = scada_gtk.AscensorVistaPozo(model = a_model)
        a_ctrl = plc.ControladorAscensor(a_model, a_view)
        asc.append( (a_model, a_view, a_ctrl) )

    # Registro los ascensores en el edificio.
    for m, v, c in asc:
        model.agregar_ascensor(m)

    # Genero la vista del edificio.
    vista = scada_gtk.EdificioVistaGtk(asc)
    # Configuro el controlador del edificio.    
    c = plc.ControladorEdificio(model, vista, asc)

    # Inicio el sistema.
    model.start()

    if not escenario is None:
        escenario.aplicar(model)

    gtk.main()

